// WorkerManager.js - Web Worker管理器

/**
 * Worker管理器类 - 负责创建和管理Web Worker实例
 */
class WorkerManager {
  constructor() {
    this.workers = {};
    this.callbacks = new Map();
    this.messageId = 0;
    this.isSupported = typeof Worker !== 'undefined';
  }

  /**
   * 创建一个新的Web Worker
   * @param {string} workerName - Worker的名称标识
   * @param {string} workerPath - Worker文件的路径
   * @returns {Promise<Worker>} Worker实例
   */
  createWorker(workerName, workerPath) {
    return new Promise((resolve, reject) => {
      if (!this.isSupported) {
        console.warn('Web Workers 不受当前浏览器支持');
        reject(new Error('Web Workers 不受支持'));
        return;
      }

      try {
        const worker = new Worker(workerPath, { type: 'module' });
        
        // 存储Worker
        this.workers[workerName] = worker;
        
        // 设置消息处理器
        worker.onmessage = (e) => this._handleMessage(workerName, e);
        
        // 设置错误处理器
        worker.onerror = (error) => this._handleError(workerName, error);
        
        // 监听初始化完成
        const initCallback = (data) => {
          if (data.action === 'INITIALIZED') {
            console.log(`Worker ${workerName} 已初始化`);
            this.callbacks.delete(`init_${workerName}`);
            resolve(worker);
          }
        };
        
        this.callbacks.set(`init_${workerName}`, initCallback);
        
      } catch (error) {
        console.error(`创建Worker ${workerName} 失败:`, error);
        reject(error);
      }
    });
  }

  /**
   * 获取已创建的Worker实例
   * @param {string} workerName - Worker名称
   * @returns {Worker|null} Worker实例或null
   */
  getWorker(workerName) {
    return this.workers[workerName] || null;
  }

  /**
   * 向Worker发送消息并等待响应
   * @param {string} workerName - Worker名称
   * @param {string} action - 操作类型
   * @param {any} data - 发送的数据
   * @param {Object} options - 选项
   * @returns {Promise<any>} Worker处理结果
   */
  postMessage(workerName, action, data = {}, options = {}) {
    return new Promise((resolve, reject) => {
      const worker = this.getWorker(workerName);
      
      if (!worker) {
        reject(new Error(`Worker ${workerName} 不存在`));
        return;
      }

      if (!this.isSupported) {
        // 如果浏览器不支持Worker，直接执行降级策略
        console.warn(`Web Worker ${workerName} 不可用，使用主线程计算`);
        this._fallbackCalculation(action, data, options)
          .then(resolve)
          .catch(reject);
        return;
      }

      // 生成唯一的消息ID
      const msgId = `msg_${this.messageId++}`;
      
      // 设置响应回调
      const callback = (response) => {
        if (response.success) {
          resolve(response.result);
        } else {
          reject(new Error(response.error || '处理失败'));
        }
        this.callbacks.delete(msgId);
      };

      this.callbacks.set(msgId, callback);
      
      // 发送消息
      try {
        worker.postMessage({
          id: msgId,
          action,
          data,
          options
        });
      } catch (error) {
        console.error(`向Worker ${workerName} 发送消息失败:`, error);
        this.callbacks.delete(msgId);
        reject(error);
      }
    });
  }

  /**
   * 终止Worker
   * @param {string} workerName - Worker名称
   */
  terminateWorker(workerName) {
    const worker = this.getWorker(workerName);
    if (worker) {
      worker.terminate();
      delete this.workers[workerName];
      console.log(`Worker ${workerName} 已终止`);
    }
  }

  /**
   * 终止所有Worker
   */
  terminateAll() {
    Object.keys(this.workers).forEach(workerName => {
      this.terminateWorker(workerName);
    });
  }

  /**
   * 处理来自Worker的消息
   * @private
   * @param {string} workerName - Worker名称
   * @param {MessageEvent} e - 消息事件
   */
  _handleMessage(workerName, e) {
    const { id, action, success, result, error } = e.data;
    
    // 如果有消息ID，调用相应的回调
    if (id && this.callbacks.has(id)) {
      const callback = this.callbacks.get(id);
      callback(e.data);
      return;
    }
    
    // 处理初始化消息或其他无ID消息
    if (action === 'INITIALIZED') {
      const initCallback = this.callbacks.get(`init_${workerName}`);
      if (initCallback) {
        initCallback(e.data);
      }
    } else {
      console.warn(`未处理的Worker消息:`, e.data);
    }
  }

  /**
   * 处理Worker错误
   * @private
   * @param {string} workerName - Worker名称
   * @param {ErrorEvent} error - 错误事件
   */
  _handleError(workerName, error) {
    console.error(`Worker ${workerName} 错误:`, error);
    // 可以在这里添加全局错误处理逻辑
  }

  /**
   * 降级计算 - 当Web Worker不可用时在主线程执行计算
   * @private
   * @param {string} action - 操作类型
   * @param {any} data - 数据
   * @param {Object} options - 选项
   * @returns {Promise<any>} 计算结果
   */
  _fallbackCalculation(action, data, options) {
    return new Promise((resolve, reject) => {
      try {
        // 根据操作类型执行相应的降级计算
        switch (action) {
          case 'PROCESS_STARS': {
            // 简化的星表处理逻辑，支持分批加载
            let filteredStars = [...data.stars];
            
            // 应用亮度过滤
            if (options.minBrightness) {
              filteredStars = filteredStars.filter(star => star.magnitude >= options.minBrightness);
            }
            
            // 按亮度排序（亮星优先）
            filteredStars.sort((a, b) => a.magnitude - b.magnitude);
            
            // 应用亮度过滤
            if (options.maxBrightness) {
              filteredStars = filteredStars.filter(star => star.magnitude <= options.maxBrightness);
            }
            
            // 处理批次
            const batchSize = options.batchSize || 1000;
            const currentBatch = options.currentBatch || 0;
            const startIndex = currentBatch * batchSize;
            const endIndex = startIndex + batchSize;
            const batchStars = filteredStars.slice(startIndex, endIndex);
            
            // 简化的颜色映射和大小计算
            const particlePositions = [];
            const colors = [];
            const sizes = [];
            
            batchStars.forEach(star => {
              // 简化的RA/Dec到3D坐标转换
              const raRad = (star.ra * Math.PI) / 180;
              const decRad = (star.dec * Math.PI) / 180;
              const distance = options.distance || 100;
              
              particlePositions.push(
                distance * Math.cos(decRad) * Math.cos(raRad),
                distance * Math.sin(decRad),
                distance * Math.cos(decRad) * Math.sin(raRad)
              );
              
              // 简化的颜色（基于光谱类型或默认白色）
              colors.push(1, 1, 1); // 默认白色
              
              // 简化的大小计算（基于星等）
              const size = Math.max(0.5, 10 - star.magnitude * 0.5);
              sizes.push(size);
            });
            
            resolve({
              positions: new Float32Array(particlePositions),
              colors: new Float32Array(colors),
              sizes: new Float32Array(sizes),
              metadata: batchStars,
              count: batchStars.length,
              isLastBatch: endIndex >= filteredStars.length,
              totalProcessed: Math.min(endIndex, filteredStars.length),
              totalAvailable: filteredStars.length
            });
            break;
          }
          case 'PROCESS_CONSTELLATIONS': {
            // 简化的星座处理逻辑
            const constellationResults = [];
            const distance = options.distance || 100;
            
            Object.entries(data.constellationLines).forEach(([name, lines]) => {
              const constellationLines = [];
              
              lines.forEach(line => {
                // 查找连接的星星
                const startStar = data.stars.find(s => s.id === line[0]);
                const endStar = data.stars.find(s => s.id === line[1]);
                
                if (startStar && endStar) {
                  // 简化的坐标转换
                  const convertTo3D = (ra, dec) => {
                    const raRad = (ra * Math.PI) / 180;
                    const decRad = (dec * Math.PI) / 180;
                    return [
                      distance * Math.cos(decRad) * Math.cos(raRad),
                      distance * Math.sin(decRad),
                      distance * Math.cos(decRad) * Math.sin(raRad)
                    ];
                  };
                  
                  const startPos = convertTo3D(startStar.ra, startStar.dec);
                  const endPos = convertTo3D(endStar.ra, endStar.dec);
                  
                  constellationLines.push({
                    start: startPos,
                    end: endPos,
                    startStar: startStar.name,
                    endStar: endStar.name
                  });
                }
              });
              
              if (constellationLines.length > 0) {
                constellationResults.push({
                  name,
                  lines: constellationLines,
                  visible: true // 降级模式下默认全部可见
                });
              }
            });
            
            resolve(constellationResults);
            break;
          }
          case 'GENERATE_MILKY_WAY_PARTICLES': {
            // 简化的银河粒子生成，支持分批
            const batchSizeParticles = options.batchSize || 500;
            const currentBatchParticles = options.currentBatch || 0;
            const totalParticles = Math.min(data.particleCount, 5000); // 限制总量
            
            // 使用固定种子确保批次一致性
            let seed = options.seed || 42;
            const pseudoRandom = () => {
              const x = Math.sin(seed++) * 10000;
              return x - Math.floor(x);
            };
            
            const milkyWayParticlePositions = [];
            const startIndexParticles = currentBatchParticles * batchSizeParticles;
            const endIndexParticles = Math.min(startIndexParticles + batchSizeParticles, totalParticles);
            
            // 设置初始种子偏移
            seed += startIndexParticles * 100;
            
            for (let i = startIndexParticles; i < endIndexParticles; i++) {
              // 简化的银河系分布
              const r = pseudoRandom() * 80 + 20;
              const theta = pseudoRandom() * Math.PI * 2;
              const phi = (pseudoRandom() - 0.5) * Math.PI * 0.2; // 扁平分布
              
              // 添加一些随机性
              const x = r * Math.cos(theta) * Math.cos(phi) + (pseudoRandom() - 0.5) * 10;
              const y = r * Math.sin(phi) + (pseudoRandom() - 0.5) * 10;
              const z = r * Math.sin(theta) * Math.cos(phi) + (pseudoRandom() - 0.5) * 10;
              
              // 粒子大小（基于位置的密度）
              const size = 0.5 + pseudoRandom() * 1.5;
              
              // 粒子颜色（淡黄色到白色）
              const rColor = 0.8 + pseudoRandom() * 0.2;
              const gColor = 0.7 + pseudoRandom() * 0.3;
              const bColor = 0.5 + pseudoRandom() * 0.5;
              
              milkyWayParticlePositions.push(x, y, z, size, rColor, gColor, bColor);
            }
            
            resolve({
              particles: new Float32Array(milkyWayParticlePositions),
              count: milkyWayParticlePositions.length / 7, // 每个粒子7个值
              isLastBatch: endIndexParticles >= totalParticles,
              totalProcessed: endIndexParticles,
              totalAvailable: totalParticles
            });
            break;
          }
          case 'CALCULATE_PLANET_POSITION': {
            // 简化的行星位置计算
            const angle = (2 * Math.PI * data.time) / data.planet.orbitalPeriod;
            resolve({
              position: {
                x: data.planet.distance * Math.cos(angle),
                y: 0,
                z: data.planet.distance * Math.sin(angle)
              },
              rotation: (2 * Math.PI * data.time) / data.planet.rotationPeriod
            });
            break;
          }
          default:
            reject(new Error(`未实现的降级计算: ${action}`));
        }
      } catch (error) {
        reject(error);
      }
    });
  }
}

// 创建单例实例
const workerManager = new WorkerManager();

/**
 * 初始化星表数据Worker
 * @returns {Promise<Worker>} Worker实例
 */
export async function initStarDataWorker() {
  return await workerManager.createWorker(
    'starDataWorker',
    '/src/workers/StarDataWorker.js'
  );
}

/**
 * 初始化轨道计算Worker
 * @returns {Promise<Worker>} Worker实例
 */
export async function initOrbitalCalculationWorker() {
  return await workerManager.createWorker(
    'orbitalCalculationWorker',
    '/src/workers/OrbitalCalculationWorker.js'
  );
}

/**
 * 处理星表数据
 * @param {Array} stars - 原始星表数据
 * @param {Object} options - 处理选项
 * @param {Object} options.viewFrustum - 视锥体数据
 * @param {number} options.batchSize - 批次大小
 * @param {number} options.currentBatch - 当前批次索引
 * @param {number} options.maxMagnitude - 最大星等
 * @param {number} options.magnitudeScale - 星等缩放因子
 * @param {boolean} options.useLOD - 是否启用LOD系统
 * @param {number} options.cameraDistance - 相机距离（用于LOD计算）
 * @param {boolean} options.sortByMagnitude - 是否按星等排序
 * @param {boolean} options.updateVisibility - 是否更新可见性
 * @returns {Promise<Object>} 处理后的星表数据
 */
export async function processStarData(stars, options = {}) {
  return await workerManager.postMessage('starDataWorker', 'PROCESS_STARS', { stars }, options);
}

/**
 * 处理星座数据
 * @param {Array} stars - 星表数据
 * @param {Object} constellationLines - 星座连线定义
 * @param {Object} options - 处理选项
 * @param {Object} options.viewFrustum - 视锥体数据
 * @param {number} options.distance - 距离
 * @param {boolean} options.useFrustumCulling - 是否启用视锥体剔除
 * @returns {Promise<Array>} 处理后的星座数据
 */
export async function processConstellationData(stars, constellationLines, options = {}) {
  return await workerManager.postMessage(
    'starDataWorker', 
    'PROCESS_CONSTELLATIONS', 
    { stars, constellationLines }, 
    options
  );
}

/**
 * 计算星座中心点
 * @param {Array} constellations - 星座数据
 * @param {string} constellationName - 星座名称
 * @param {number} scale - 缩放因子
 * @returns {Promise<Object>} 中心点坐标
 */
export async function calculateConstellationCenter(constellations, constellationName, scale = 100) {
  return await workerManager.postMessage(
    'starDataWorker', 
    'CALCULATE_CONSTELLATION_CENTER', 
    { constellations, constellationName }, 
    { scale }
  );
}

/**
 * 生成银河粒子数据
 * @param {number} particleCount - 粒子数量
 * @param {Object} options - 处理选项
 * @param {Object} options.viewFrustum - 视锥体数据
 * @param {number} options.batchSize - 批次大小
 * @param {number} options.currentBatch - 当前批次索引
 * @param {number} options.seed - 随机种子（固定种子用于批次一致性）
 * @param {boolean} options.useFrustumCulling - 是否启用视锥体剔除
 * @returns {Promise<Object>} 银河粒子数据和批次信息
 */
export async function generateMilkyWayParticles(particleCount = 2000, options = {}) {
  return await workerManager.postMessage(
    'starDataWorker', 
    'GENERATE_MILKY_WAY_PARTICLES', 
    { particleCount }, 
    options
  );
}

/**
 * 计算行星位置
 * @param {Object} planet - 行星数据
 * @param {number} time - 时间
 * @param {Object} options - 选项
 * @returns {Promise<Object>} 行星位置和旋转状态
 */
export async function calculatePlanetPosition(planet, time, options = {}) {
  return await workerManager.postMessage('orbitalCalculationWorker', 'CALCULATE_PLANET_POSITION', { planet, time }, options);
}

/**
 * 计算所有行星位置
 * @param {Object} planetData - 行星数据
 * @param {number} time - 时间
 * @param {Object} options - 选项
 * @returns {Promise<Object>} 所有行星位置数据
 */
export async function calculateAllOrbitalPositions(planetData, time, options = {}) {
  return await workerManager.postMessage(
    'orbitalCalculationWorker', 
    'CALCULATE_ALL_POSITIONS', 
    { planetData, time }, 
    options
  );
}

/**
 * 计算轨道点
 * @param {Object} planet - 行星数据
 * @param {number} numPoints - 点数量
 * @returns {Promise<Array>} 轨道点数组
 */
export async function calculateOrbitPoints(planet, numPoints = 120) {
  return await workerManager.postMessage(
    'orbitalCalculationWorker', 
    'CALCULATE_ORBIT_POINTS', 
    { planet }, 
    { numPoints }
  );
}

/**
 * 计算所有轨道
 * @param {Object} planetData - 行星数据
 * @param {number} numPoints - 点数量
 * @returns {Promise<Object>} 所有轨道数据
 */
export async function calculateAllOrbits(planetData, numPoints = 120) {
  return await workerManager.postMessage(
    'orbitalCalculationWorker', 
    'CALCULATE_ALL_ORBITS', 
    { planetData }, 
    { numPoints }
  );
}

/**
 * 优化轨道计算
 * @param {Object} planetData - 行星数据
 * @param {number} time - 时间
 * @param {Object} viewDistance - 视图距离
 * @returns {Promise<Object>} 优化后的轨道数据
 */
export async function optimizedOrbitalCalculation(planetData, time, viewDistance) {
  return await workerManager.postMessage(
    'orbitalCalculationWorker', 
    'OPTIMIZED_CALCULATION', 
    { planetData, time, viewDistance }
  );
}

/**
 * 清理所有Worker
 */
export function cleanupWorkers() {
  workerManager.terminateAll();
}

// 导出Worker管理器实例（可选）
export { workerManager };